/*
 * Vector.h
 *
 * 描述: 尝试使用C语言实现一个自动扩容的数据类型，并且尽量做到类似C++或者Java的封装形式。
 * 
 * --------------------------------------------------------------------------
 *
 *      Copyright (c) 2021 LiuBingyi
 *      SimpleMark is licensed under Mulan PubL v2.
 *      You can use this software according to the terms and conditions of the Mulan PubL v2.
 *      You may obtain a copy of Mulan PubL v2 at:
 *               http://license.coscl.org.cn/MulanPubL-2.0
 *      THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 *      EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 *      MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 *      See the Mulan PubL v2 for more details.
 * 
 */

/**
 *  本文档为Vector.c的头文件,所有应该公开的函数都已经包含在已初始化的结构体`vector_Method`之中，
 *  设计上应该通过这个外部变量内包含的函数指针来调用所需的函数，而不应该直接调用。
 * 
 *  目前所包含的函数尚不够完善，从面向对象的思想来说。封装的不是很完善，仍有一些功能待提供。
 *  缺乏多线程的支持。
 * 
 * author:LiuBingyi
 * email:cecillearofa@163.com
 * time:2021-7-21 1:05
 */
#pragma once

#ifndef _VECTOR_H
#define _VECTOR_H

#include "basic_lib.h"

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus  extern "C" */

#undef size_vector
typedef unsigned long long size_vector;

typedef void* elementObj;
typedef const void* constElementObj;

//#ifdef _EXPORTING
typedef struct {
    size_vector capacity;
    size_vector capacityIncrement;
    size_vector elementCount;
    memSize elementSize;
    elementObj container;
} vectorBase;
//#endif
/* 
    用以声明Vector类型(指针)，应该使用 `vector_Method.constructor()` 的返回值来初始化。
    一个Vector假设了其包含的所有元素都应该是等长的（在初始化时指定），并基于这一点工作。
    但请注意，整个函数库并*不保证*所有元素等长，如果传递了过长或过短的元素，可能会导致未知问题。
    目前还没有提供多线程的支持，所有操作并不能保障线程安全。
*/
typedef vectorBase* Vector;


int freeAllVector();
int vectorCopy(Vector dest, Vector src);


//已经实现了一个全局变量`vector_Method`。如果你不需要自己实现方法,请不要声明这个类型。
struct VectorMethod {
    //Vector最基本的构造函数。
    Vector (*constructor)(size_vector capacity, size_vector increment, memSize elementSize);
    /*
        返回Vector的内容（不是副本）。提供这个函数是为了方便使用者利用它将Vector的内容复制到某个数组里，
        尽管你可以直接访问Vector->container，但是为了封装的完整性我还是觉得应该提供。
        之所以不直接提供副本，主要是我认为作为C语言使用者，自己管理内存或许更为妥当。
    */
    constElementObj (*container)(Vector this);
    //在this指向的vector的末尾插入一个元素，每次应当只添加一个obj
    int (*add)(Vector this, constElementObj obj);
    //在index指定的位置插入元素，如果index大于vector所有的元素量,可能会引发未知错误
    int (*insert)(Vector this, constElementObj obj, size_vector index);
    //删除index指定位置的元素，如果index大于vector所有的元素量,可能会引发未知错误
    int (*erase)(Vector this, size_vector index);
    //在this指向的vector的末尾删去一个元素，每次应当只减少一个obj
    int (*sub)(Vector this);
    //将index指定位置的元素替换成obj,如果index大于vector所有的元素量,可能会引发未知错误
    int (*place)(Vector this, constElementObj obj, size_vector index);
    //返回Vector中与obj的值相同的第一个元素的序列,如果未找到则返回-1（LONG_LONG_MAX）。
    //为保障稳定性，使用顺序查找，故而效率较低。
    size_vector (*indexOf)(Vector this, constElementObj obj);
    //返回index指定位置元素的指针
    constElementObj (*index)(Vector this, size_vector index);
    //排序Vector中的元素,暂未实现
    int (*sort)(Vector this, void(*rule));
    //在this指向的vector的末尾删去一个元素，每次应当只减少一个obj。与sub不同的是,如果删除的元素数量减少到临界线，这个函数会对Vector的内存进行缩减。
    int (*remove)(Vector this);
    //删除this指向末尾的rmCount个元素,注意会对Vector进行缩减操作
    int (*removeMultiple)(Vector this, size_vector rmCount);
    //返回this中已有的元素个数
    size_vector (*length)(Vector this);
    // 释放Vector所拥有的内存，包括存放Vector内容的内存和Vector本身的内存。
    int (*close)(Vector this);
};

DLLDECLSPEC extern const struct VectorMethod vector_Method;

#ifdef __cplusplus
}
#endif /* __cplusplus  extern "C" */

#endif